﻿using EmailManagementSoftware.Model;
using EmailManagementSoftware.Model.DAO.Interfaces;
using EmailManagementSoftware.View.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EmailManagementSoftware.Presenter
{
    public class AppPresenter
    {
        public IMainWindowView _MainWindowView { get; set; }
        public IManageEmailCredentialsView _ManageEmailCredentialsView { get; set; }
        public IEmailMessageView _EmailMessageView { get; set; }

        public IAppDAO _AppDAO { get; set; }
        public User _LoggedInUser { get; private set; }


        public AppPresenter(IMainWindowView mainWindowView, IAppDAO appDAO)
        {
            _MainWindowView = mainWindowView;
            _AppDAO = appDAO;
        }


        public void btnLogIn_Click(object sender, EventArgs e)
        {
            //basic validation
            if (String.IsNullOrWhiteSpace(_MainWindowView._Username) || String.IsNullOrWhiteSpace(_MainWindowView._Password))
            {
                MessageBox.Show((Form)_MainWindowView, "None of the input fields can be empty!", "Invalid input", MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1);
            }
            else
            {
                try
                {
                    //call the Model to get the logged user, then display an appropriate message
                    _LoggedInUser = _AppDAO.getUser(_MainWindowView._Username, _MainWindowView._Password);
                }
                catch (Exception ex)
                {
                    MessageBox.Show((Form)_MainWindowView, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                    return;
                }

                if (_LoggedInUser == null)
                {
                    MessageBox.Show((Form)_MainWindowView, "Invalid credentials!", "Invalid input", MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1);
                }
                else
                {
                    #region population the main window with the username and the emails subjects:
                    try
                    {
                        //1. get the emails messages subjects' list
                        List<EmailMessage> emailMessages = (List<EmailMessage>)_AppDAO.getEmailMessages(_LoggedInUser._idUser);


                        //2.
                        _MainWindowView.updateGUIAfterLogIn(emailMessages);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show((Form)_MainWindowView, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                    }
                    #endregion
                }
            }
        }

        public void btnManageYourEmailCredentials_Click(object sender, EventArgs e)
        {
            EmailCredentials emailCredentials;


            //retrieve the email credentials
            try
            {
                emailCredentials = _AppDAO.getEmailCredentials(_LoggedInUser._idUser);


                if (emailCredentials == null)
                {
                    emailCredentials = new EmailCredentials();
                }
                        

                //update the current email credentials of the user
                this._LoggedInUser._EmailCredentials = emailCredentials;


                //create and show window
                _ManageEmailCredentialsView = new ManageEmailCredentialsView(this);
                ((Form)_ManageEmailCredentialsView).ShowDialog((MainWindowView)this._MainWindowView);
            }
            catch (Exception ex)
            {
                MessageBox.Show((Form)_MainWindowView, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1);
                return;
            }
        }

        public void btnLogOut_Click(object sender, EventArgs e)
        {
            _MainWindowView.updateGUIAfterLogOut();
        }

        public void btnAdd_Click(object sender, EventArgs e)
        {
            _EmailMessageView = new EmailMessageView(this);
            _EmailMessageView._WindowTitle = "Add Email Message";
            ((Form)_EmailMessageView).ShowDialog((MainWindowView)this._MainWindowView);


            _MainWindowView.updateStateWhenCheckedListBoxFocusIsLost();
        }

        public void btnEdit_Click(object sender, EventArgs e)
        {
            _EmailMessageView = new EmailMessageView(this);
            _EmailMessageView._WindowTitle = "Edit Email Message";


            #region populating the GUI with the selected email
                //1.get the selected email
                EmailMessage checkedEmailMessage = _MainWindowView.checkedEmailMessage;
                //2.populate the EmailMessageView Form
                _EmailMessageView._Subject = checkedEmailMessage._emailSubject;
                _EmailMessageView._Recipient = checkedEmailMessage._recipient;
                _EmailMessageView._Body = checkedEmailMessage._emailBody;

                List<EmailAttachement> emailAttachements = (List<EmailAttachement>)_AppDAO.getEmailAttachements(checkedEmailMessage._idEmailMessage);

            if (emailAttachements != null)
            {
                foreach (var emailAttachement in emailAttachements)
                {
                    string fullPath = emailAttachement._attachementPath;
                    string shortPath = convertFullPathToShortPath(fullPath);

                    _EmailMessageView._ShortPathFullPathPairs.Add(shortPath, fullPath);

                    //display each string attachement in the listbox
                    _EmailMessageView.addStringAttachement(shortPath);
                } 
            }

            #endregion

            #region update the state of lbxAttachements in the EmailMessage Window depending on the number of attachements found in the database //  updateStateOfListBox() {btnClearAll.Enabled = (lbxAttachements.Items.Count>0);btnRemove.Enabled = (lbxAttachements.SelectedIndex != -1);}

                _EmailMessageView.updateStateOfListBox();
            #endregion


            ((Form)_EmailMessageView).ShowDialog((MainWindowView)this._MainWindowView);


            _MainWindowView.updateStateWhenCheckedListBoxFocusIsLost();
        }

        public void btnDelete_Click(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show((Form)_MainWindowView, "Delete the selected message(s)?", "Confirm deletion!", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);

            if (result == DialogResult.Yes)
            {
                _AppDAO.deleteEmailMessage(_MainWindowView.checkedEmailMessage._idEmailMessage);
            }


            try
            {
                _MainWindowView.repopulateClbEmailsSubjects((List<EmailMessage>)_AppDAO.getEmailMessages(_LoggedInUser._idUser));
            }
            catch (Exception ex)
            {
                MessageBox.Show((Form)_MainWindowView, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
            }


            _MainWindowView.updateStateWhenCheckedListBoxFocusIsLost();
        }

        public void btnSend_Click(object sender, EventArgs e)
        {
            //TODO
            throw new System.NotImplementedException();
        }

        public void clbEmailsSubjects_Click(object sender, EventArgs e)
        {
            _MainWindowView.updateGUIOnclbEmailsSubjectsClick();
        }

        public void btnSaveManageEmailCredentials_Click(object sender, EventArgs e)
        {
            //validating the input, then using the model for either insertion or update
            //1. check for null/empty input and for not_a_number SMTPPort
            if (String.IsNullOrWhiteSpace(_ManageEmailCredentialsView._EmailAddress) || String.IsNullOrWhiteSpace(_ManageEmailCredentialsView._Password) || String.IsNullOrWhiteSpace(_ManageEmailCredentialsView._SMTPServer) || String.IsNullOrWhiteSpace(_ManageEmailCredentialsView._SMTPPort))
            {
                MessageBox.Show((Form)_ManageEmailCredentialsView, "None of the input fields can be empty!", "Invalid input", MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1); 
            }
            else
            {
                if(Regex.IsMatch(_ManageEmailCredentialsView._SMTPPort, @"^\d+$") == false)
                {
                    MessageBox.Show((Form)_ManageEmailCredentialsView, "The SMTPPort can only be an integer!", "Invalid input", MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1);
                    return;
                }


                try
                {
                    //if emailAddress is null, this is the first time the email credentials are inserted
                    if (String.IsNullOrWhiteSpace(_LoggedInUser._EmailCredentials._emailAddress))
                    {
                        int aux = Int32.Parse(_ManageEmailCredentialsView._SMTPPort);
                        _AppDAO.insertEmailCredentials(_LoggedInUser._idUser, _ManageEmailCredentialsView._EmailAddress, _ManageEmailCredentialsView._Password, _ManageEmailCredentialsView._SMTPServer, aux);
                    }
                    else
                    {
                        int aux = Int32.Parse(_ManageEmailCredentialsView._SMTPPort);
                        _AppDAO.updateEmailCredentials(_LoggedInUser._idUser, _ManageEmailCredentialsView._EmailAddress, _ManageEmailCredentialsView._Password, _ManageEmailCredentialsView._SMTPServer, aux);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show((Form)_ManageEmailCredentialsView, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                }


                //after updating the database, the loggedUser follows
                _LoggedInUser._EmailCredentials._emailAddress = _ManageEmailCredentialsView._EmailAddress;
                _LoggedInUser._EmailCredentials._password = _ManageEmailCredentialsView._Password;
                _LoggedInUser._EmailCredentials._smtpServer = _ManageEmailCredentialsView._SMTPServer;
                _LoggedInUser._EmailCredentials._smtpPort = Int32.Parse(_ManageEmailCredentialsView._SMTPPort);


                (_ManageEmailCredentialsView as Form).Dispose();
            }            
        }

        public void btnCancelManageEmailCredentials_Click(object sender, EventArgs e)
        {
            ((Form)_ManageEmailCredentialsView).Dispose();
        }

        public void btnSaveEmailMessage_Click(object sender, EventArgs e)
        {
            //avoid processing empty input
            if (String.IsNullOrWhiteSpace(_EmailMessageView._Subject) || String.IsNullOrWhiteSpace(_EmailMessageView._Recipient))
            {
                MessageBox.Show((Form)_ManageEmailCredentialsView, "Neither the subject nor the recipient input fields can be empty!", "Invalid input", MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1);
                return;
            }


            List<EmailAttachement> toBeAddedAttachements = null;

            //get the email message's attachements 
            String[] fullPathsAttachements = _EmailMessageView._ShortPathFullPathPairs.Values.ToArray();


            try
            {
                if (fullPathsAttachements.Length != 0)
                {
                    EmailAttachement emailAttachement;
                    toBeAddedAttachements = new List<EmailAttachement>();

                    foreach (string item in fullPathsAttachements)
                    {
                        emailAttachement = new EmailAttachement();
                        emailAttachement._attachementPath = item;
                        //emailAttachement._idEmailMessage = TO BE added;
                        toBeAddedAttachements.Add(emailAttachement);
                    }
                }


                //if the window is opended for addition
                if (_EmailMessageView._WindowTitle.Equals("Add Email Message"))
                {
                    //insert emailMessage in db except the attachements
                    _AppDAO.insertEmailMessage(this._LoggedInUser._idUser, _EmailMessageView._Subject, _EmailMessageView._Recipient, _EmailMessageView._Body);

                    //retrieve the auto-generated idEmailMessage of the above record from the database 
                    EmailMessage lastInsertedEmailMessage = _AppDAO.getTheLastRecord();
                    int idEmailMessage = lastInsertedEmailMessage._idEmailMessage;

                    if (toBeAddedAttachements != null)
                    {
                        //set the idEmailMessages of all email attachements
                        foreach (EmailAttachement item in toBeAddedAttachements)
                        {
                            item._idEmailMessage = idEmailMessage;
                        }

                        //insert email Attachements of the above emailMessage into the database
                        _AppDAO.insertEmailAttachements(idEmailMessage, toBeAddedAttachements);
                    }
                    
                }

                //the window is opened for editing an email message
                else
                {
                    //update emailMessage in db without except the attachements
                    _AppDAO.updateEmailMessage(_EmailMessageView._Subject, _EmailMessageView._Recipient, _EmailMessageView._Body, _MainWindowView.checkedEmailMessage._idEmailMessage);

                    //delete all the previous email attachements from db
                    _AppDAO.deleteAllEmailAttachements(_MainWindowView.checkedEmailMessage._idEmailMessage);

                    //set the idEmailMessages of all email attachements
                    int idEmailMessage = _MainWindowView.checkedEmailMessage._idEmailMessage;

                    if (toBeAddedAttachements != null)
                    {
                        foreach (EmailAttachement item in toBeAddedAttachements)
                        {
                            item._idEmailMessage = idEmailMessage;
                        }

                        //insert into the databse the email attachements chosen by the user
                        _AppDAO.insertEmailAttachements(idEmailMessage, toBeAddedAttachements);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show((Form)_EmailMessageView, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                return;
            }


            //update GUI
            _MainWindowView.repopulateClbEmailsSubjects((List<EmailMessage>)_AppDAO.getEmailMessages(_LoggedInUser._idUser));


            (_EmailMessageView as Form).Dispose();
        }

        public void btnCancelEmailMessage_Click(object sender, EventArgs e)
        {
            (_EmailMessageView as Form).Dispose();
        }

        public void btnAddAttachement_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Multiselect = true;


            openFileDialog.InitialDirectory = "c:\\";
            openFileDialog.Filter = "All Files (*.*)|*.*";
            //openFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            openFileDialog.RestoreDirectory = true;
            openFileDialog.Title = "Select your Attachement";

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                String[] attachements = openFileDialog.SafeFileNames;
                String[] fullPathsAttachements = openFileDialog.FileNames;

                int count = attachements.Length;
                for (int i = 0; i< count; i++)
                {
                    //appending the new attachements to the listbox
                    _EmailMessageView.addStringAttachement(attachements[i]);

                    _EmailMessageView._ShortPathFullPathPairs.Add(attachements[i],fullPathsAttachements[i]);
                }

                _EmailMessageView.updateStateOfListBox();
            }
        }

        public void btnRemove_Click(object sender, EventArgs e)
        {
            //from the dictionary
            _EmailMessageView._ShortPathFullPathPairs.Remove(_EmailMessageView._SelectedAttachement);

            //from the Attachements list
            _EmailMessageView.removeStringAttachement(_EmailMessageView._SelectedAttachementIndex);
        }

        public void btnClearAll_Click(object sender, EventArgs e)
        {
            //from the Attachements list
            _EmailMessageView.removeAllStringAttachements();

            //from the dictionary
            _EmailMessageView._ShortPathFullPathPairs.Clear();



        }


        string convertFullPathToShortPath(string FullPath)
        {
            return Path.GetFileName(FullPath);
        }
    }
}
